//
//  BQNavigator.m
//  BQNavigator
//
//  Created by Zhiqiang Bao on 15-4-1.
//  Copyright (c) 2015年 Zhiqiang Bao. All rights reserved.
//

#import "BQNavigator.h"
#import <objc/runtime.h>

@interface BQNavigator ()

@property (nonatomic, strong) BQRouter *router;
@property (nonatomic, strong) BQNavigatorRunner *runner;

@end

@implementation BQNavigator

#pragma mark -

+ (BQNavigator *)sharedInstance
{
    static dispatch_once_t once_token;
    static BQNavigator *sharedInstance = nil;
    
    dispatch_once(&once_token, ^{
        if (sharedInstance == nil) {
            sharedInstance = [[self alloc] init];
        }
    });
    
    return sharedInstance;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.router = [[BQRouter alloc] init];
        self.runner = [[BQNavigatorRunner alloc] init];
    }
    return self;
}

#pragma mark - Register API

- (void)registerClass:(Class)cls toEvent:(NSString *)event option:(BQNavigatorOrderType)type
{
    [self registerClassName:NSStringFromClass(cls) toEvent:event option:type];
}

- (void)registerClassName:(NSString *)clsName toEvent:(NSString *)event option:(BQNavigatorOrderType)type
{
    if (clsName.length == 0 || event.length == 0) return;
    
    BQNavigatorOrder *order = [BQNavigatorOrder orderWithEvent:event className:clsName type:type];
    
    [_router registerOrder:order toRunner:_runner];
}

- (void)registerObject:(UIViewController<BQNavigatable> *)object toEvent:(NSString *)event option:(BQNavigatorOrderType)type
{
    if (object == nil || event.length == 0) return;
    
    NSString *className = NSStringFromClass([object class]);
    
    BQNavigatorOrder *order = [BQNavigatorOrder orderWithEvent:event className:className type:type];
    
    order.lastObject = object;
}

- (void)registerClassName:(NSString *)clsName toEvent:(NSString *)event
{
    [self registerClassName:clsName toEvent:event option:BQNavigatorOrderTypeMultiton];
}

- (void)registerClass:(Class)cls toEvent:(NSString *)event
{
    [self registerClass:cls toEvent:event option:BQNavigatorOrderTypeMultiton];
}

- (void)registerObject:(UIViewController<BQNavigatable> *)object toEvent:(NSString *)event
{
    [self registerObject:object toEvent:event option:BQNavigatorOrderTypeMultiton];
}

- (void)registerEntryPlist:(NSString *)filePath
{
    
}

#pragma mark - Map API

- (void)mapEvent:(NSString *)first toEvent:(NSString *)second
{
    if (first.length == 0 || second.length == 0) return;
    
    BQNavigatorOrder *orderSecond = (BQNavigatorOrder *)[_router registeredOrderByEvent:second];
    
    BQNavigatorOrder *orderFirst = [BQNavigatorOrder orderWithEvent:orderSecond.event className:orderSecond.className type:orderSecond.type];
    
    [_router mapOrder:orderFirst toOrder:orderSecond];
}

#pragma mark - Open API

- (void)openEvent:(NSString *)event withParam:(NSDictionary *)param inCarrier:(UIViewController *)ctl animated:(BOOL)animated
{
    BOOL shouldOpen = YES;
    
    if ([_delegate respondsToSelector:@selector(navigator:shouldOpen:withParam:)]) {
        shouldOpen = [_delegate navigator:self shouldOpen:event withParam:param];
    }
    
    if (shouldOpen) {
        
        if ([_delegate respondsToSelector:@selector(navigator:willOpen:withParam:)]) {
            [_delegate navigator:self willOpen:event withParam:param];
        }
        
        BQNavigatorRunnerOption *option = [BQNavigatorRunnerOption optionWithCarrier:ctl param:param animated:animated];
        [_router executeOrderEvent:event withOption:option];
        
        if ([_delegate respondsToSelector:@selector(navigator:didOpen:withParam:)]) {
            [_delegate navigator:self didOpen:event withParam:param];
        }
    }
}

- (void)openEvent:(NSString *)event withParam:(NSDictionary *)param animated:(BOOL)animated
{
    [self openEvent:event withParam:param inCarrier:nil animated:animated];
}

- (void)openEvent:(NSString *)event animated:(BOOL)animated
{
    [self openEvent:event withParam:nil animated:animated];
}

@end
